<template>
  <transition name="fade">
    <div v-if="visible" class="custom-loading-overlay">
      <div class="message">
        <span v-for="(char, index) in typedText" :key="index">{{ char }}</span>
      </div>
    </div>
  </transition>
</template>

<script setup lang="ts">
import { ref, watch, onMounted } from 'vue'
import type { Ref } from 'vue'

interface FullScreenLoadingProps {
  visible: boolean
  /**
   * Array of messages to display in sequence.
   */
  messages?: string[]
  /**
   * Total time (ms) to cycle through the messages. Each message gets totalDelay / messages.length.
   */
  totalDelay?: number
  /**
   * Typing speed in ms per character.
   */
  typingSpeed?: number
}

const props = defineProps<FullScreenLoadingProps>()

const typedText: Ref<string> = ref('')

// Fix the types for timers
let currentTimeout: ReturnType<typeof setTimeout> | null = null
let currentInterval: ReturnType<typeof setInterval> | null = null

function clearTimers() {
  if (currentTimeout !== null) {
    clearTimeout(currentTimeout)
    currentTimeout = null
  }
  if (currentInterval !== null) {
    clearInterval(currentInterval)
    currentInterval = null
  }
}

function startTypingSequence() {
  typedText.value = ''
  clearTimers()
  const msgs = props.messages ?? []
  if (!msgs.length) return

  const total = props.totalDelay ?? 4000 // default total 4s
  const chunk = Math.floor(total / msgs.length)
  let msgIndex = 0

  function typeMessage(message: string) {
    typedText.value = ''
    let i = 0
    currentInterval = setInterval(() => {
      typedText.value += message[i]
      i++
      if (i >= message.length) {
        if (currentInterval) {
          clearInterval(currentInterval)
          currentInterval = null
        }
        currentTimeout = setTimeout(() => {
          msgIndex++
          if (msgIndex < msgs.length && props.visible) {
            typeMessage(msgs[msgIndex])
          }
        }, chunk)
      }
    }, props.typingSpeed ?? 100)
  }

  typeMessage(msgs[msgIndex])
}

onMounted(() => {
  if (props.visible) {
    startTypingSequence()
  }
})

watch(
  () => props.visible,
  (newVal) => {
    if (newVal) {
      startTypingSequence()
    } else {
      clearTimers()
      typedText.value = ''
    }
  }
)
</script>

<style scoped>
.custom-loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-color: rgba(113, 75, 103, 0.4); /* system color with some transparency */
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.message {
  background-color: #f2f2f2dd; /* changed to a light grey background */
  padding: 20px 30px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.2);
  color: #333; /* changed text color to a darker grey */
  font-size: 24px;
  font-weight: 600;
  font-family: "Microsoft YaHei", "Noto Sans SC", sans-serif;
}

.fade-enter-active, .fade-leave-active {
  transition: opacity 1.5s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
</style>
